package com.wk.springboot.config;

import com.wk.springboot.filter.MyFilter;
import com.wk.springboot.realm.HashRealm;
import com.wk.springboot.realm.MD5Realm;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.crypto.hash.Sha1Hash;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.Primary;
import org.springframework.web.filter.DelegatingFilterProxy;

/**
 * @Classname ShiroBeanConfig
 * @Description shiro用到的所有bean
 * @Date 2020/5/18 23:01
 * @Author by weikai
 */
@Configuration
public class ShiroBeanConfig {



  /**
   * 自定义模块验证器
   * @return
   */
  @Bean
  public ModularRealmAuthenticator modularRealmAuthenticator(){
    ModularRealmAuthenticator modularRealmAuthenticator = new ModularRealmAuthenticator();
    modularRealmAuthenticator.setAuthenticationStrategy(atLeastOneSuccessfulStrategy());
    return modularRealmAuthenticator;
  }

  /**
   * 自定义realm
   */
  @Bean
  public MD5Realm md5Realm() {
    MD5Realm myRealm = new MD5Realm();
    myRealm.setCredentialsMatcher(hashedCredentialsMatcher());
    return myRealm;
  }

  /**
   * 自定义realm
   */
  @Bean
  public HashRealm hashRealm() {
    HashRealm myRealm = new HashRealm();
    myRealm.setCredentialsMatcher(shalHashedCredentialsMatcher());
    return myRealm;
  }

  /**
   * 配置securityManager
   */
  @Bean
  public DefaultWebSecurityManager securityManager() {
    DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
    defaultWebSecurityManager.setAuthenticator(modularRealmAuthenticator());
    /**
     * 在这里设置realms，而不是在modularRealmAuthenticator里
     */
    List realms = new ArrayList<>();
    realms.add(md5Realm());
    realms.add(hashRealm());
    defaultWebSecurityManager.setRealms(realms);
    return defaultWebSecurityManager;
  }

  /**
   * 后处理器会自动为Spring配置的Shiro对象调用init（）和destroy（）方法，因此您不必 1）为每个bean定义指定一个init-method和destroy-method属性，以及
   * 2）甚至知道哪些Shiro对象要求调用这些方法。
   */
  @Bean
  public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
    LifecycleBeanPostProcessor lifecycleBeanPostProcessor = new LifecycleBeanPostProcessor();
    return lifecycleBeanPostProcessor;
  }

  /**
   * 为Spring配置的bean启用Shiro注解。仅在lifecycleBeanProcessor运行之后运行：
   */
  @Bean
  @DependsOn("lifecycleBeanPostProcessor")
  public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
    DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
    defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
    return defaultAdvisorAutoProxyCreator;
  }

  @Bean
  public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Autowired DefaultWebSecurityManager securityManager) {
    AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
    authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
    return authorizationAttributeSourceAdvisor;
  }


  @Bean
  public ShiroFilterFactoryBean shiroFilter() {
    ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
    shiroFilterFactoryBean.setSecurityManager(securityManager());

    shiroFilterFactoryBean.setLoginUrl("/html/login.html");
    shiroFilterFactoryBean.setSuccessUrl("/html/hello.html");
    shiroFilterFactoryBean.setUnauthorizedUrl("/html/unauthor.html");

    Map<String, String> filterChainDefinitionMap = new HashMap<>();
    filterChainDefinitionMap.put("/html/login.html", "anon");
    filterChainDefinitionMap.put("/login", "anon");
    filterChainDefinitionMap.put("/guest/**", "anon");
    filterChainDefinitionMap.put("/**/*.js", "anon");
    filterChainDefinitionMap.put("/**/*.css", "anon");
    filterChainDefinitionMap.put("/html/user.html", "roles[weikai]");
    filterChainDefinitionMap.put("/html/note.html", "roles[shiro]");
    filterChainDefinitionMap.put("/**", "authc");
    shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
    return shiroFilterFactoryBean;
  }

  /**
   * 密码加密对象
   * @return
   */
  @Bean
  public HashedCredentialsMatcher hashedCredentialsMatcher(){
    HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
    hashedCredentialsMatcher.setHashAlgorithmName(Md5Hash.ALGORITHM_NAME);
    hashedCredentialsMatcher.setHashIterations(1024);
    return hashedCredentialsMatcher;
  }

  /**
   * 密码加密对象
   * @return
   */
  @Bean
  public HashedCredentialsMatcher shalHashedCredentialsMatcher(){
    HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
    hashedCredentialsMatcher.setHashAlgorithmName(Sha1Hash.ALGORITHM_NAME);
    hashedCredentialsMatcher.setHashIterations(1024);
    return hashedCredentialsMatcher;
  }

/*  @Bean
  public MyFilter myFilter(@Autowired ShiroFilterFactoryBean shiroFilterFactoryBean){
    return new MyFilter();
  }

  @Bean
  public MyFilter myFilter2(@Autowired ShiroFilterFactoryBean shiroFilterFactoryBean){
    return new MyFilter();
  }*/

  @Bean
  public AtLeastOneSuccessfulStrategy atLeastOneSuccessfulStrategy(){
    return new AtLeastOneSuccessfulStrategy();
  }

}
